﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PluginInterface;
using Buccontrols;
using System.Runtime.InteropServices;

namespace Buccaneer
{
    public partial class PluginDaddy : Form
    {
        public PluginDaddy(PluginServices ph)
        {
            InitializeComponent();

            this.Plugins = ph;
            this.Plugins.RegisterAction(new StartDraggingAction(this));
            this.tabs = new List<PluginCouple>();
            this.afnames = new List<string>();
            this.afargs = new List<string[]>();

            foreach (var c in Controls)
            {
                if (c is MdiClient)
                {
                    this.mdiParentArea = c as MdiClient;
                    break;
                }
            }
        }

        List<PluginCouple> tabs;
        List<string> afnames;
        List<string[]> afargs;
        DragForm dragForm;
        MdiClient mdiParentArea;
        bool handlingActRequests = false;

        public PluginServices Plugins;

        public PluginCouple selectedPlugin
        {
            get
            {
                foreach (PluginCouple tab in tabs)
                {
                    if (tab.Parent.Instance.MainInterface.Name.StartsWith(this.ActiveMdiChild.Name))
                    {
                        return tab;
                    }
                }
                return null;
            }
        }

        #region Public Functions

        public void AddTab(IPlugin plugin)
        {
            this.tabs.Add(new PluginCouple(selectedPlugin, plugin));
        }

        public void RemoveTab(string name)
        {
            foreach (PluginCouple tab in tabs)
            {
                if (tab.Parent.Instance.MainInterface.Name == name)
                {
                    this.tabs.Remove(tab);
                    break;
                }
            }
        }

        public void AddPlugin(IPlugin plugin)
        {
            if (this.ActiveMdiChild.Name.StartsWith("LoadPluginForm"))
            {
                this.ActiveMdiChild.Close();
            }
            foreach (PluginCouple tab in tabs)
            {
                if (tab.Parent.Instance.MainInterface.Name == this.ActiveMdiChild.Name)
                {
                    plugin.MainInterfaceParent = this;
                    plugin.MainInterface.Name = plugin.Name + this.MdiChildren.Length.ToString();
                    plugin.Initialize();
                    plugin.MainInterface.Show();
                    plugin.MainInterface.Activate();
                    tab.Generate(plugin);
                    return;
                }
            }
            plugin.MainInterfaceParent = this;
            plugin.MainInterface.Name = plugin.Name + this.MdiChildren.Length.ToString();
            plugin.Initialize();
            plugin.MainInterface.Show();
            plugin.MainInterface.Activate();
            tabs.Add(new PluginCouple(selectedPlugin, plugin));
        }

        public void RemovePlugin(string name)
        {
            foreach (Form form in this.MdiChildren)
            {
                if (form.Name == name)
                {
                    form.Close();
                    break;
                }
            }
        }

        public void ActRequest(string afname, string[] args)
        {
            this.afnames.Add(afname);
            this.afargs.Add(args);
        }

        public void HandleActRequests()
        {
            if (handlingActRequests) return;
            handlingActRequests = true;
            for (int i = 0; i < afnames.Count; i++)
            {
                Plugins.Act(afnames[i], afargs[i]);
            }
            afnames = null;
            afargs = null;
            afnames = new List<string>();
            afargs = new List<string[]>();
            handlingActRequests = false;
        }

        public void StartDragging(string[] args)
        {
            string name = args[0];

            foreach (Form form in this.MdiChildren)
            {
                if (form.Name == name)
                {
                    form.SuspendLayout();
                    form.Visible = false;
                    form.StartPosition = FormStartPosition.Manual;
                    dragForm = new DragForm(
                        new Rectangle(this.mdiParentArea.PointToScreen(new Point(0, 0)), this.mdiParentArea.ClientSize),
                        this.mdiParentArea.PointToScreen(form.Location),
                        form.Size
                    );
                    dragForm.ShowDialog();
                    switch (dragForm.Result)
                    {
                        case DragFormResult.Return:
                            form.Location = this.mdiParentArea.PointToClient(dragForm.Location);
                            form.Size = dragForm.Size;
                            form.Visible = true;
                            form.ResumeLayout(false);
                            break;
                        case DragFormResult.Close:
                            form.Visible = true;
                            form.Close();
                            break;
                        case DragFormResult.Options:
                            form.Location = this.mdiParentArea.PointToClient(dragForm.Location);
                            form.Size = dragForm.Size;
                            form.Visible = true;
                            form.ResumeLayout(false);
                            break;
                        case DragFormResult.Add:
                            form.Location = this.mdiParentArea.PointToClient(dragForm.Location);
                            form.Size = dragForm.Size;
                            form.Visible = true;
                            form.ResumeLayout(false);
                            form.Activate();
                            this.Plugins.Act("addform", null);
                            break;
                        default:
                            form.Visible = true;
                            form.ResumeLayout(false);
                            break;
                    }

                    break;
                }
            }
        }

        #endregion

        private void Daddy_Activated(object sender, EventArgs e)
        {
            HandleActRequests();
        }

        private void PluginDaddy_FormClosing(object sender, FormClosingEventArgs e)
        {
            foreach (Form frm in this.MdiChildren)
                frm.Close();
        }

        private void PluginDaddy_Load(object sender, EventArgs e)
        {
            this.BackgroundImageLayout = ImageLayout.Stretch;
            SetMdiClientBorder(false);
        }

        private const int GWL_EXSTYLE = -20;
        private const int WS_EX_CLIENTEDGE = 512;
        

        [DllImport("user32.dll")]
        static extern long GetWindowLong(System.IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        static extern long SetWindowLong(System.IntPtr hWnd, int nIndex, long dwNewLong);

        private void SetMdiClientBorder(bool showBorder)
        {
            foreach (MdiClient c in this.Controls)
            {
                long windowLong = GetWindowLong(c.Handle, GWL_EXSTYLE);
                if (showBorder)
                {
                    windowLong = (windowLong | WS_EX_CLIENTEDGE);
                }
                else
                {
                    windowLong = (windowLong
                                & ~WS_EX_CLIENTEDGE);
                }
                SetWindowLong(c.Handle, GWL_EXSTYLE, windowLong);
                c.Width = (c.Width + 1);
                c.BackgroundImage = Options.GetResource("back") as Image;
                c.BackColor = Color.Lime;
                break;
            }
        }
    }

    public class StartDraggingAction : PluginAction
    {
        public StartDraggingAction(PluginDaddy pluginDaddy)
        {
            base.name = "startdragging";
            base.func = new ActionFunction(this.StartDragging);
            base.pars.Add("formname", "the form to get started with dragging");
            base.pluginDaddy = pluginDaddy;
        }

        public void StartDragging(string[] args)
        {
            (base.pluginDaddy).StartDragging(args);
        }
    }
}
